﻿using System;
using System.Drawing;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.Serialization;
using CloudShot.Core.Utils;

namespace CloudShot.Core.Types
{
	/// <summary>
	/// Represents information about taken screenshot.
	/// </summary>
	[Serializable]
	public sealed class ShotInfo : IXmlSerializable
	{
		/// <summary>
		/// Thumbnail size in pixels.
		/// </summary>
		private const int THUMB_SIZE = 48;

		/// <summary>
		/// Gets or sets name of the screenshot.
		/// </summary>
		public string Name { get; set; }

		/// <summary>
		/// Gets or sets path/link to the screenshot file.
		/// </summary>
		public string Path { get; set; }

		/// <summary>
		/// Gets a thumbnail for the screenshot.
		/// </summary>
		public Image Thumbnail { get; private set; }

		/// <summary>
		/// Creates instance of <see cref="ShotInfo"/> class.
		/// </summary>
		public ShotInfo()
		{
		}

		/// <summary>
		/// Creates instance of <see cref="ShotInfo"/> class.
		/// </summary>
		/// <param name="name">A name of the <see cref="screenshot"/>.</param>
		/// <param name="path">A path or link to the screenshot file.</param>
		/// <param name="screenshot">A screenshot taken from screen.</param>
		public ShotInfo(string name, string path, Image screenshot)
		{
			Name = name;
			Path = path;
			SetThumbnail(screenshot);
		}

		/// <summary>
		/// Sets <see cref="Thumbnail"/> for the screenshot.
		/// </summary>
		/// <param name="screenshot">The screenshot <see cref="Image"/>.</param>
		/// <remarks>
		/// Before set the <see cref="Thumbnail"/> will be automatically resized to <see cref="THUMB_SIZE"/>, if it is needed.
		/// </remarks>
		public void SetThumbnail(Image screenshot)
		{
			if (screenshot.Width <= THUMB_SIZE && screenshot.Height <= THUMB_SIZE)
				Thumbnail = screenshot;

			Thumbnail = ImgResizer.FixedSize(screenshot, THUMB_SIZE, THUMB_SIZE, Color.White);
		}

		#region Implementation of IXmlSerializable

		/// <summary>
		/// This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return null (Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute"/> to the class.
		/// </summary>
		/// <returns>
		/// An <see cref="T:System.Xml.Schema.XmlSchema"/> that describes the XML representation of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"/> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"/> method.
		/// </returns>
		public XmlSchema GetSchema()
		{
			return null;
		}

		/// <summary>
		/// Generates an object from its XML representation.
		/// </summary>
		/// <param name="reader">The <see cref="T:System.Xml.XmlReader"/> stream from which the object is deserialized. </param>
		public void ReadXml(XmlReader reader)
		{
			while (reader.NodeType == XmlNodeType.Element)
			{
				using (XmlReader inner = reader.ReadSubtree())
				{
					XElement root = XElement.Load(inner);

					//skip empty nodes and nodes with no elements
					if (root.IsEmpty || !root.HasElements)
					{
						reader.Skip();
						continue;
					}

					XElement element = root.Element("Name");
					if (element != null) Name = element.Value;

					element = root.Element("Path");
					if (element != null) Path = element.Value;

					inner.Close();
				}

				reader.Skip();
				break;
			}
		}

		/// <summary>
		/// Converts an object into its XML representation.
		/// </summary>
		/// <param name="writer">The <see cref="T:System.Xml.XmlWriter"/> stream to which the object is serialized. </param>
		public void WriteXml(XmlWriter writer)
		{
			writer.WriteElementString("Name", Name);
			writer.WriteElementString("Path", Path);
		}

		#endregion
	}
}